﻿using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
using Tycho.Runtime;

namespace Tycho.Peyote {
    /// <summary>
    /// Interaction logic for ListGlyph.xaml
    /// </summary>
    public partial class ListGlyph : UserControl {
        private readonly AnyObject List;
        private readonly Environment Environment;

        public ListGlyph (AnyObject list, Environment environment) {
            List = list;
            InitializeComponent ();

            Environment = environment;
            DataContext = this;

            PopulateListItems (GetListItems (List));
        }

        /// <summary>
        /// Gets the items from the list object. Uses integer indexing
        /// and the count property to find items, not IEnumerable interface
        /// as this may never stop returning items (an infinite sequence perhaps)
        /// this is a slighly different object to a plain list.
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        private List<AnyObject> GetListItems (AnyObject list) {
            List<AnyObject> items = new List<AnyObject> ();

            Environment.Transaction (delegate () {
                int size = list.Count;
                for (int n = 0; n < size; n++) {
                    items.Add (list [n]);
                }
            }, items.Clear);

            return items;
        }

        void PopulateListItems(List<AnyObject> items) {
            foreach (AnyObject item in items) {
                ListView.Children.Add (Environment.Presenter.Present (item));
            }
        }
    }

    class ListPresenter : GlyphPresenter {
        public ListPresenter () : base ("list", new SimplePrototypeSchema (new [] {Symbols.RuntimeCount}, new [] {Symbols.RuntimeIndexGet})) {
        }

        public override System.Windows.UIElement Present (AnyObject obj, Environment environment) {
            return new ListGlyph (obj, environment);
        }
    }

    internal class SimplePrototypeSchema : SchemaObject {
        private readonly AnyObject[] Properties;
        private readonly AnyObject[] Methods;

        public SimplePrototypeSchema (AnyObject[] properties, AnyObject[] methods) {
            Properties = properties;
            Methods = methods;
        }

        public override bool Match (AnyObject results, params AnyObject [] objs) {
            AnyObject obj = objs[0];

            return Properties.All (obj.HasProperty) && Methods.All (obj.HasMethod);
        }
    }
}
